`timescale 1ns/100ps

module dcm_filter_top
#(parameter
    DATA_BW = 24
)
(
    input  I_pclk,
    input  I_rst_n,
    input  I_enable_filt,
    // video in
    input  I_vin_vsync,
    input  I_vin_hsync,
    input  I_vin_de,
    input  [ DATA_BW - 1: 0] I_vin_data, // {Y,Cb,Cr}
    // video out
    output reg O_vout_vsync,
    output reg O_vout_hsync,
    output reg O_vout_de,
    output reg [ DATA_BW - 1: 0] O_vout_data // {Y,Cb,Cr}
);

/*******************************************************************************
                                   <localparms>
*******************************************************************************/
localparam
    ONE_CHN_BW = DATA_BW / 3;

/*******************************************************************************
                                <internal signals>
*******************************************************************************/
reg  [ ONE_CHN_BW - 1: 0] data_Y_d1;
reg  [ ONE_CHN_BW - 1: 0] data_Y_d2;
reg  [ ONE_CHN_BW - 1: 0] data_Y_d3;
reg  [ ONE_CHN_BW - 1: 0] data_Y_d4;
reg  [ ONE_CHN_BW - 1: 0] data_Y_d5;
reg  [ ONE_CHN_BW - 1: 0] data_Y_d6;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d1;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d2;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d3;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d4;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d5;
reg  [ ONE_CHN_BW - 1: 0] data_Cr_d6;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d1;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d2;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d3;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d4;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d5;
reg  [ ONE_CHN_BW - 1: 0] data_Cb_d6;
reg  vsync_d1;
reg  vsync_d2;
reg  vsync_d3;
reg  vsync_d4;
reg  vsync_d5;
reg  vsync_d6;
reg  hsync_d1;
reg  hsync_d2;
reg  hsync_d3;
reg  hsync_d4;
reg  hsync_d5;
reg  hsync_d6;
reg  de_d1;
reg  de_d2;
reg  de_d3;
reg  de_d4;
reg  de_d5;
reg  de_d6;
wire [ ONE_CHN_BW - 1: 0] dcm_data_Cr;
wire [ ONE_CHN_BW - 1: 0] dcm_data_Cb;

/*******************************************************************************
                                  <module body>
*******************************************************************************/
dcm_444_to_422_filt
#(
    .DATAPATH_WIDTH(ONE_CHN_BW)
)
u_dcm_444_to_422_filt_Cb
(
    .I_sclk(I_pclk),
    .I_rst_n(I_rst_n),
    .I_dv(I_enable_filt),
    .I_data(I_vin_data[ONE_CHN_BW*2-1:ONE_CHN_BW]),
    .I_de(I_vin_de),
    .I_hsync(I_vin_hsync),
    .I_vsync(I_vin_vsync),
    .O_data(dcm_data_Cb),
    .O_de(),
    .O_hsync(),
    .O_vsync()
);

dcm_444_to_422_filt
#(
    .DATAPATH_WIDTH(ONE_CHN_BW)
)
u_dcm_444_to_422_filt_Cr
(
    .I_sclk(I_pclk),
    .I_rst_n(I_rst_n),
    .I_dv(I_enable_filt),
    .I_data(I_vin_data[ONE_CHN_BW-1:0]),
    .I_de(I_vin_de),
    .I_hsync(I_vin_hsync),
    .I_vsync(I_vin_vsync),
    .O_data(dcm_data_Cr),
    .O_de(),
    .O_hsync(),
    .O_vsync()
);

always @(posedge I_pclk or negedge I_rst_n)
    if(!I_rst_n)
        begin
        data_Y_d1 <= 0;
        data_Y_d2 <= 0;
        data_Y_d3 <= 0;
        data_Y_d4 <= 0;
        data_Y_d5 <= 0;
        data_Y_d6 <= 0;
        data_Cb_d1 <= 0;
        data_Cb_d2 <= 0;
        data_Cb_d3 <= 0;
        data_Cb_d4 <= 0;
        data_Cb_d5 <= 0;
        data_Cb_d6 <= 0;
        data_Cr_d1 <= 0;
        data_Cr_d2 <= 0;
        data_Cr_d3 <= 0;
        data_Cr_d4 <= 0;
        data_Cr_d5 <= 0;
        data_Cr_d6 <= 0;
        vsync_d1 <= 1'b0;
        vsync_d2 <= 1'b0;
        vsync_d3 <= 1'b0;
        vsync_d4 <= 1'b0;
        vsync_d5 <= 1'b0;
        vsync_d6 <= 1'b0;
        hsync_d1 <= 1'b0;
        hsync_d2 <= 1'b0;
        hsync_d3 <= 1'b0;
        hsync_d4 <= 1'b0;
        hsync_d5 <= 1'b0;
        hsync_d6 <= 1'b0;
        de_d1 <= 1'b0;
        de_d2 <= 1'b0;
        de_d3 <= 1'b0;
        de_d4 <= 1'b0;
        de_d5 <= 1'b0;
        de_d6 <= 1'b0;
        end
    else
        begin
        data_Y_d1 <= I_vin_data[ONE_CHN_BW*3-1:ONE_CHN_BW*2];
        data_Y_d2 <= data_Y_d1;
        data_Y_d3 <= data_Y_d2;
        data_Y_d4 <= data_Y_d3;
        data_Y_d5 <= data_Y_d4;
        data_Y_d6 <= data_Y_d5;
        data_Cb_d1 <= I_vin_data[ONE_CHN_BW*2-1:ONE_CHN_BW];
        data_Cb_d2 <= data_Cb_d1;
        data_Cb_d3 <= data_Cb_d2;
        data_Cb_d4 <= data_Cb_d3;
        data_Cb_d5 <= data_Cb_d4;
        data_Cb_d6 <= data_Cb_d5;
        data_Cr_d1 <= I_vin_data[ONE_CHN_BW-1:0];
        data_Cr_d2 <= data_Cr_d1;
        data_Cr_d3 <= data_Cr_d2;
        data_Cr_d4 <= data_Cr_d3;
        data_Cr_d5 <= data_Cr_d4;
        data_Cr_d6 <= data_Cr_d5;
        vsync_d1 <= I_vin_vsync;
        vsync_d2 <= vsync_d1;
        vsync_d3 <= vsync_d2;
        vsync_d4 <= vsync_d3;
        vsync_d5 <= vsync_d4;
        vsync_d6 <= vsync_d5;
        hsync_d1 <= I_vin_hsync;
        hsync_d2 <= hsync_d1;
        hsync_d3 <= hsync_d2;
        hsync_d4 <= hsync_d3;
        hsync_d5 <= hsync_d4;
        hsync_d6 <= hsync_d5;
        de_d1 <= I_vin_de;
        de_d2 <= de_d1;
        de_d3 <= de_d2;
        de_d4 <= de_d3;
        de_d5 <= de_d4;
        de_d6 <= de_d5;
        end

always @(posedge I_pclk or negedge I_rst_n)
    if(!I_rst_n)
        begin
        O_vout_data <= 0;
        O_vout_vsync <= 0;
        O_vout_hsync <= 0;
        O_vout_de <= 0;
        end
    else
        begin
        O_vout_data <= (I_enable_filt)?{data_Y_d6,dcm_data_Cb,dcm_data_Cr}
                                      :{data_Y_d6,data_Cb_d6,data_Cr_d6};
        O_vout_vsync <= vsync_d6;
        O_vout_hsync <= hsync_d6;
        O_vout_de <= de_d6;
        end
 
endmodule
